﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using Smarly.Core;
using Smarly.Core.Database;
using System.ComponentModel.DataAnnotations;
using Smarly.Forum.Bussines.Parsing;

namespace Smarly.Forum.Bussines.Model
{
	public class ThreadModel : ModelStateObject
	{
		public long Id { get; set; }

		[Required(ErrorMessage = "Поле не заполнено")]
		[StringLength(128, ErrorMessage = "Максимальная длина 128 символов")]
		public string Title { get; set; }

		[Required(ErrorMessage = "Поле не заполнено")]
		public string Value { get; set; }

		[DatabaseValidation("SectionNotFound", "Категория не найдена")]
		public string SectionHashTag { get; set; }

		public List<SectionModel> Sections { get; set; }

		public List<ThreadNote> Notes { get; set; }

		public class ThreadNote
		{
			public ThreadNote()
			{
				Clarify = new List<ClarifyNote>();
			}

			public long ThreadId { get; set; }
			public long Id { get; set; }
			[Required(ErrorMessage = "Поле не заполнено")]
			public string NoteText { get; set; }
			public string UserNick { get; set; }
			public string EmailSh1 { get; set; }
			public DateTime CreateDate { get; set; }

//			public string ThreadTitle { get; set; }

			public List<ClarifyNote> Clarify { get; set; }

//			public string SectionHashTag { get; set; }

			public bool isNew { get; set; }
			public bool AllowEdit { get; set; }

			public ThreadModel Thread { get; set; }


			public ThreadNote Get(SmarlyIdentity identity)
			{
				return SqlRepository.ExecuteProcedureReader("Forum_ThreadNote_Get",
																						 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@threadNoteId", Value = Id, Type = DbType.Int64},
			                                     	}, null,
																							(reader) =>
																							{
																								while (reader.Read())
																								{
																									ThreadId = reader.GetInt64("ThreadId");
																									Thread = new ThreadModel { Id = ThreadId, SectionHashTag = reader.GetString("SectionHashTag"), Title = reader.GetString("Title")};
																									Id = reader.GetInt64("ThreadNoteId");
																									NoteText = reader.GetString("Text");
																								}

																								return this;
																							});
			}

			public ThreadNote Post(SmarlyIdentity identity)
			{
				NoteText = ToText(NoteText);

				return SqlRepository.ExecuteProcedureReader("Forum_ThreadNote_Post",
																						 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@threadId", Value = ThreadId, Type = DbType.Int64},
			                                     		new SpParam {Name = "@value", Value = NoteText.Trim(), Type = DbType.String},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																							(reader) =>
																							{
																								while (reader.Read())
																								{
																									ThreadId = reader.GetInt64("ThreadId");
																									Thread = new ThreadModel { Id = reader.GetInt64("ThreadId"), SectionHashTag = reader.GetString("SectionHashTag") };
																									Id = reader.GetInt64("ThreadNoteId");
																									NoteText = reader.GetString("Text");
																									CreateDate = reader.GetDateTime("CreatedDate");
																									UserNick = reader.GetStringOrNull("NickName");
																									EmailSh1 = reader.GetString("EmailSh1");
																									isNew = reader.GetBoolean("IsNew");
																								}

																								return this;
																							});
			}

			public ThreadNote Put(SmarlyIdentity identity)
			{
				NoteText = ToText(NoteText);

				return SqlRepository.ExecuteProcedureReader("Forum_ThreadNote_Put",
																						 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@threadNoteId", Value = Id, Type = DbType.Int64},
			                                     		new SpParam {Name = "@value", Value = NoteText.Trim(), Type = DbType.String},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																							(reader) =>
																							{
																								while (reader.Read())
																								{
																									ThreadId = reader.GetInt64("ThreadId");
																									Thread = new ThreadModel { Id = ThreadId, SectionHashTag = reader.GetString("SectionHashTag"), Title = reader.GetString("Title") };
																									Id = reader.GetInt64("ThreadNoteId");
																								}

																								return this;
																							});
			}
	
		}

		public class ClarifyNote
		{
			public long Id { get; set; }
			public long ThreadNoteId { get; set; }
			[Required(ErrorMessage = "Поле не заполнено")]
			public string Value { get; set; }
			public int Order { get; set; }
			public string UserNick { get; set; }
			public string EmailSh1 { get; set; }
			public DateTime CreateDate { get; set; }

			public long ThreadId { get; set; }
			public string SectionHashTag { get; set; }

			public bool isNew { get; set; }

			public bool AllowEdit { get; set; }

			public ClarifyNote Post(SmarlyIdentity identity)
			{
				return SqlRepository.ExecuteProcedureReader("Forum_ClarifyNote_Post",
																						 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@threadNoteId", Value = ThreadNoteId, Type = DbType.Int64},
			                                     		new SpParam {Name = "@value", Value = Value.Trim(), Type = DbType.String},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																							(reader) =>
																							{
																								while (reader.Read())
																								{
																									ThreadId = reader.GetInt64("ThreadId");
																									SectionHashTag = reader.GetString("SectionHashTag");
																									Id = reader.GetInt64("ClarifyNoteId");
																									Value = reader.GetString("Text");
																									CreateDate = reader.GetDateTime("CreatedDate");
																									UserNick = reader.GetStringOrNull("NickName");
																									EmailSh1 = reader.GetString("EmailSh1");
																									isNew = reader.GetBoolean("IsNew");
																								}

																								return this;
																							});
			}

			public ClarifyNote Put(SmarlyIdentity identity)
			{
				return SqlRepository.ExecuteProcedureReader("Forum_ClarifyNote_Put",
																						 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@clarifyNoteId", Value = Id, Type = DbType.Int64},
			                                     		new SpParam {Name = "@value", Value = Value.Trim(), Type = DbType.String},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																							(reader) =>
																							{
/*																								while (reader.Read())
																								{
																									ThreadId = reader.GetInt64("ThreadId");
																									SectionHashTag = reader.GetString("SectionHashTag");
																									Id = reader.GetInt64("ClarifyNoteId");
																									Value = reader.GetString("Text");
																									CreateDate = reader.GetDateTime("CreatedDate");
																									UserNick = reader.GetStringOrNull("NickName");
																									EmailSh1 = reader.GetString("EmailSh1");
																									isNew = reader.GetBoolean("IsNew");
																								}*/

																								return this;
																							});
			}
		}


		public ThreadModel Get(SmarlyIdentity identity)
		{
			return SqlRepository.ExecuteProcedureReader("Forum_Thread_Get",
																					 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@threadId", Value = Id, Type = DbType.Int64},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																						(reader) =>
																						{
																							int batchNum = 0;
																							do
																							{
																								switch (batchNum)
																								{
																									case 0:
																										while (reader.Read())
																										{
																											SectionHashTag = reader.GetString("SectionHashTag");
																											Title = reader.GetString("Name");
																										}
																										break;
																									case 1:
																										Notes = new List<ThreadNote>();
																										while (reader.Read())
																										{
																											Notes.Add(new ThreadNote
																																	{
																																		Id = reader.GetInt64("ThreadNoteId"),
																																		NoteText = reader.GetString("Text"),
																																		CreateDate = reader.GetDateTime("CreatedDate"),
																																		UserNick = reader.GetStringOrNull("NickName"),
																																		EmailSh1 = reader.GetString("EmailSh1"),
																																		ThreadId = Id,
																																		Thread = this,
																																		AllowEdit = reader.GetBoolean("AllowEdit"),
																																	});
																										}
																										break;
																									case 2:
																										var list = new List<ClarifyNote>();
																										while (reader.Read())
																										{
																											list.Add(new ClarifyNote
																											{
																												Id = reader.GetInt64("ClarifyNoteId"),
																												ThreadNoteId = reader.GetInt64("ThreadNoteId"),
																												Value = reader.GetString("Text"),
																												Order = reader.GetInt32("Order"),
																												CreateDate = reader.GetDateTime("CreatedDate"),
																												UserNick = reader.GetStringOrNull("NickName"),
																												EmailSh1 = reader.GetString("EmailSh1"),
																												AllowEdit = reader.GetBoolean("AllowEdit"),
																											});
																										}

																										foreach (var note in Notes)
																										{
																											note.Clarify = list.Where(x => x.ThreadNoteId == note.Id).OrderBy(x => x.Order).ToList();
																										}
																										break;
																									default:
																										throw new ApplicationException("Additional batch select");

																								}
																								batchNum++;
																							} while (reader.NextResult());


																							return this;
																						});

		}


		public ThreadModel Post(SmarlyIdentity identity)
		{
			Value = ToText(Value);
			Title = Title.Trim();

			return SqlRepository.ExecuteProcedureReader("Forum_Thread_Create",
																					 new List<SpParam>
			                                     	{
			                                     		new SpParam {Name = "@sectionHashTag", Value = SectionHashTag, Type = DbType.String},
			                                     		new SpParam {Name = "@title", Value = Title, Type = DbType.String},
			                                     		new SpParam {Name = "@value", Value = Value, Type = DbType.String},
			                                     		new SpParam {Name = "@userId", Value = identity.UserId, Type = DbType.Guid},
			                                     	}, null,
																						(reader) =>
																						{

																							while (reader.Read())
																							{
																								Id = reader.GetInt64("ThreadId");
																							}
																							return this;
																						});
		}

		private static string ToText(string bbCode)
		{
			string str = Regex.Replace(bbCode, @"\[pre=(.)+?](.|\s)+?\[/pre]", (m) =>
			{
				string value = m.Value;
				value = value.Replace("\r\n", "[br]");
				value = value.Replace("[br]", "&#91;br]");
				value = value.Replace("[i]", "&#91;i]");
				value = value.Replace("[b]", "&#91;b]");
				return value;
			}).Replace("\r", string.Empty).Replace("\n", "[br]").ToHtml();

			str = Regex.Replace(str, @"\<pre(.|\s)+?\</pre>", (m) => m.Value.Replace("&#91;i]", "[i]").Replace("&#91;b]", "[b]").Replace("&#91;br]", "\n"));

/*
			if (!str.Trim().StartsWith("<"))
				str = "<p>" + str + "</p>";
*/

			return str;
		}
	}
}